<script setup lang="ts">
import {
  ref,
  computed,
  watch,
  watchEffect,
  onUnmounted,
  onDeactivated,
  onActivated,
} from "vue";
import { throttle } from "@/utils/common";

const delay = (time: number) => {
  return new Promise((resolve) => {
    setTimeout(resolve, time);
  });
};
export interface listItem {
  id: number;
  title?: string;
  content?: string;
  date?: string;
  img: string;
}
export interface Props {
  list: listItem[];
  width?: number;
  autoplay?: boolean;
  interval?: number;
  showDots?: boolean;
  index?: number;
}
const props = withDefaults(defineProps<Props>(), {
  list: () => [
    {
      id: 1,
      title: "标题1",
      content: "内容1",
      date: "2022-03-01",
      img: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
    },
    {
      id: 2,
      title: "标题2",
      content: "内容3",
      date: "2022-03-01",
      img: "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg",
    },
    {
      id: 3,
      title: "标题3",
      content: "内容3",
      date: "2022-03-01",
      img: "https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg",
    },
    {
      id: 4,
      title: "标题4",
      content: "内容3",
      date: "2022-03-01",
      img: "https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg",
    },
  ],
  width: 400,
  autoplay: true,
  interval: 3,
  showDots: true,
  index: 0,
});
const emits = defineEmits(["next", "prev", "update:value"]);
const list = ref<listItem[]>(props.list);

list.value = [...list.value, list.value[0]];
//设置容器宽度
let itemWidth = ref(props.width); //容器宽度
//计算移动宽度
const moveWidth = computed(() => {
  return itemWidth.value * targetIndex.value;
});
//设置目标索引
const targetIndex = ref(props.index);
//设置光标索引
const cursorIndex = ref(0);
//点击事件
const handleClick = (index: number) => {
  timeNum = 0;
  cursorIndex.value = index;
  targetIndex.value = index;
};

//点击左边事件
const clickLfet = throttle(() => {
  emits("prev", targetIndex.value);
  timeNum = 0;
  if (targetIndex.value == 0) {
    noTransliton = true;
    targetIndex.value = list.value.length - 1;

    setTimeout(() => {
      targetIndex.value--;
      cursorIndex.value = list.value.length - 2;
    }, 0);

    return;
  }
  targetIndex.value--;
  cursorIndex.value--;
}, 300);
//是否禁止移动
let noTransliton = false;
//点击右边事件
const clickRight = throttle(() => {
  emits("next", targetIndex.value);
  timeNum = 0;
  cursorIndex.value++;
  targetIndex.value++;
}, 300);

watch(targetIndex, (newIndex, oldIndex) => {
  // 最后一张时无缝衔接
  if (newIndex == list.value.length - 1 && oldIndex == list.value.length - 2) {
    // 设置光标索引为0
    cursorIndex.value = 0;
    // 设置300毫秒后，目标索引为0，并且设置noTransliton为true
    setTimeout(() => {
      targetIndex.value = 0;
      noTransliton = true;
    }, 300);
  }

  if (targetIndex.value !== 0 && targetIndex.value !== list.value.length - 1) {
    noTransliton = false;
  }
  if (targetIndex.value < list.value.length - 1) {
    emits("update:value", targetIndex.value);
  }
});

let timeNum: number = 0; //控制定时器重新开始计时
let isHover = ref(false);

let loop = ref(true);
const run = async (time: number) => {
  if (!props.autoplay) {
    return;
  }
  while (loop.value) {
    if (timeNum == time) {
      if (!isHover.value) {
        targetIndex.value++;
        cursorIndex.value++;
      }
      timeNum = 0;
    }
    // 鼠标移入停止轮播
    if (!isHover.value) {
      timeNum++;
    }
    await delay(1000);
  }
};
onActivated(() => {
  loop.value = true;
  run(props.interval);
});
onDeactivated(() => {
  loop.value = false;
});
</script>

<template>
  <div style="display: flex; justify-content: center">
    <div
      @mouseenter="isHover = true"
      @mouseleave="isHover = false"
      class="swiper"
      :style="{ '--itemWidth': itemWidth + 'px' }"
    >
      <div
        class="img-item"
        :ref="'imgItem'"
        :class="{ 'no-transition': noTransliton }"
        v-for="(item, index) in list"
        :style="{
          left: itemWidth * index + 'px',
          '--moveWidth': -moveWidth + 'px',
        }"
        :key="item.id"
      >
        <img :src="item.img" alt="" />
      </div>
      <div class="cursors" v-if="showDots">
        <div
          class="cursor-item"
          v-for="(item, index) in list.slice(0, list.length - 1)"
          :key="item.id"
          :class="{ active: index === cursorIndex }"
          @click="handleClick(index)"
        ></div>
      </div>
      <div class="arrow">
        <div
          :class="{ 'left-enter': isHover }"
          @click="clickLfet"
          class="left-arrow"
        ></div>
        <div
          @click="clickRight"
          :class="{ 'right-enter': isHover }"
          class="right-arrow"
        ></div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="less">
.swiper {
  width: var(--itemWidth);
  height: 200px;
  background-color: #d3dce6;
  position: relative;
  overflow: hidden;
  .img-item {
    transform: translateX(var(--moveWidth));
    width: var(--itemWidth);
    height: 100%;
    position: absolute;
    transition: all 0.3s;
    img {
      width: 100%;
      height: 100%;
    }
    // z-index: 9999;
  }
  .no-transition {
    transition: none;
  }
  .cursors {
    position: absolute;
    bottom: 5px;
    left: 50%;
    transform: translateX(-50%);
    .cursor-item {
      width: 10px;
      height: 10px;
      background-color: #fff;
      border-radius: 50%;
      display: inline-block;
      margin-right: 10px;
      cursor: pointer;
      &.active {
        background-color: #409eff;
      }
    }
  }

  .arrow {
    width: 100%;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    justify-content: space-between;
    // padding: 0 10px;
    .left-arrow {
      // transform: rotate(180deg);
      opacity: 0;
      width: 30px;
      height: 30px;
      //   background-color: #a9b3bf;
      background-color: #d3dce6;
      border-radius: 50%;
      transition: all 0.3s;
      position: relative;
      cursor: pointer;
      &:hover {
        opacity: 0.6;
        background-color: #a9b3bf;
      }
      &::after {
        content: "";
        display: block;
        width: 5px;
        height: 5px;
        border-left: 2px solid #fff;
        border-bottom: 2px solid #fff;
        position: absolute;
        left: 56%;
        top: 50%;
        transform: translate(-50%, -50%) rotate(45deg);
      }
    }
    .left-enter {
      transform: translateX(30%);
      opacity: 1;
    }
    .right-arrow {
      opacity: 0;
      width: 30px;
      height: 30px;
      //   background-color: #a9b3bf;
      background-color: #d3dce6;
      border-radius: 50%;
      transition: all 0.3s;
      position: relative;
      cursor: pointer;
      &:hover {
        opacity: 0.6;
        background-color: #a9b3bf;
      }
      &::after {
        content: "";
        display: block;
        width: 5px;
        height: 5px;
        border-left: 2px solid #fff;
        border-bottom: 2px solid #fff;
        position: absolute;
        left: 49%;
        top: 50%;
        transform: translate(-50%, -50%) rotate(225deg);
      }
    }
    .right-enter {
      transform: translateX(-30%);
      opacity: 1;
    }
  }
}
</style>
